﻿/*
 * Class description: manage  store and business for get article comment list
 * @Reviewed by: Anhtu79
 * @Reviewed date: 22/06/12
 * */
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using HelloMinasan.Domain;
using NHibernate;
using NHibernate.Transform;
using HelloMinasan.Domain.Dtos;
using HelloMinasan.UserDefinedType.Dtos;
using HelloMinasan.UserDefinedType;
using HelloMinasan.Framework.Helpers;
using NHibernate.Criterion;
using HelloMinasan.Data;
using HelloMinasan.Data.Extend;

namespace HelloMinasan.Data.Nhibernate.Extend
{
    public class SongRepository : Repository<HelloMinasan.Domain.Song>, ISongRepository
    {
        public TypeSong GetTypeSong(int id)
        {
            return Session.QueryOver<TypeSong>().Where(x => x.Id == id).List().FirstOrDefault();
        }
        public IEnumerable<Song> GetSongsByUsername(int userId, int page = 1)
        {
            //Tu converted
            //return db.Songs
            //    .Where(x => x.Owners == db.Users.Where(u => u.Username == username).FirstOrDefault().UserId)
            //    .OrderByDescending(x => x.PostedDate)
            //    .Skip((page - 1) * ConstantData.RecordOnOnePage)
            //    .Take(ConstantData.RecordOnOnePage).ToList();

            //int userId = int.Parse(username);
            IList<Song> results;
            results = Session.QueryOver<Song>()
                .Where(x => x.User.Id == userId)
                .Skip((page - 1) * ConstantData.RecordOnOnePage)
                .Take(ConstantData.RecordOnOnePage).List();

            return results;
        }

        public IEnumerable<Song> GetAllSongs(int page = 1)
        {
            //return db.Songs
            //    .OrderByDescending(x => x.SongName)
            //    .Skip((page - 1) * ConstantData.RecordOnOnePage)
            //    .Take(ConstantData.RecordOnOnePage).ToList();

            IList<Song> results;
            results = Session.QueryOver<Song>()
                .Skip((page - 1) * ConstantData.RecordOnOnePage)
                .Take(ConstantData.RecordOnOnePage).List();

            return results;
        }

        public Song GetSongContent(int songId, bool isUpView = false)
        {
            //var obj = db.Songs.Where(x => x.SongId == songId).FirstOrDefault();
            //if (obj != null)
            //{
            //    if (isUpView)
            //        obj.SongView += 1;
            //    db.SaveChanges();
            //}
            //return obj;

            var obj = FindAll(x => x.Id == songId).FirstOrDefault();
            if (obj != null)
            {
                if (isUpView)
                    obj.SongView += 1;
                SaveOrUpdate(obj);
            }
            return obj;
        }

        public int AddSong(Song songObject)
        {
            //db.Songs.Add(songObject);
            //db.SaveChanges();
            ////TO DO
            //return songObject.SongId;

            SaveOrUpdate(songObject);
            return songObject.Id;
        }

        public void DeleteSong(int songId)
        {
            //var obj = db.Songs.Where(x => x.SongId == songId).FirstOrDefault();
            //if (obj == null)
            //{
            //    throw new Exception("Song id is not exist!");
            //}
            //var lyricContent = db.LyricDetails.Where(x => x.SongId == obj.SongId);
            //foreach (var item in lyricContent) { db.LyricDetails.Remove(item); }

            //var quizs = db.QuestionQuizs.Where(x => x.SongId == obj.SongId);
            //foreach (var item in quizs) { db.QuestionQuizs.Remove(item); }

            //var blanks = db.QuestionBlanks.Where(x => x.SongId == obj.SongId);
            //foreach (var item in blanks) { db.QuestionBlanks.Remove(item); }

            //var favourites = db.FavouriteSongs.Where(x => x.SongId == obj.SongId);
            //foreach (var item in favourites) { db.FavouriteSongs.Remove(item); }

            //db.Songs.Remove(obj);
            //db.SaveChanges();

            var obj = FindAll(x => x.Id == songId).FirstOrDefault();
            if (obj == null)
            {
                throw new Exception("Song id is not exist!");
            }
            var lyricContent = Session.QueryOver<LyricDetail>().Where(x => x.Song.Id == obj.Id).List();
            foreach (var item in lyricContent) 
            { 
                Delete(item);
            }

            var quizs = Session.QueryOver<QuestionQuiz>().Where(x => x.SongId == obj.Id).List();
            foreach (var item in quizs) 
            { 
                Delete(item);
            }

            var blanks = Session.QueryOver<QuestionBlank>().Where(x => x.Song.Id == obj.Id).List();
            foreach (var item in blanks) { Delete(item); }

            var favourites = Session.QueryOver<FavouriteSong>().Where(x => x.Song.Id == obj.Id).List();
            foreach (var item in favourites) { Delete(item); }

            Delete(obj);
            
            //TODO: No need to do so complicated like above -> hibernate can delete casdcase mode
            //var obj = FindAll(x => x.SongId == songId).FirstOrDefault();
            //Delete(obj);
        }

        public void LockSong(int songId, bool isLocked = true)
        {
            //var obj = db.Songs.Where(x => x.SongId == songId).FirstOrDefault();
            //if (obj == null)
            //{
            //    throw new Exception("Song id is not exist!");
            //}
            //obj.IsLocked = isLocked;
            //db.SaveChanges();

            var obj = FindAll(x => x.Id == songId).FirstOrDefault();
            if (obj == null)
            {
                throw new Exception("Song id is not exist!");
            }
            obj.IsLocked = isLocked;
            SaveOrUpdate(obj);
        }

        public IEnumerable<Song> GetRelativeSong(Song songObj)
        {
            //return db.Songs
            //    .Where(x => x.Owners == songObj.Owners)
            //    .OrderBy(r => Guid.NewGuid())
            //    .Take(ConstantData.RecordOnOnePage).ToList();

            IList<Song> results;
            results = Session.QueryOver<Song>()
                .Where(x => x.User.Id == songObj.User.Id)
                .Take(ConstantData.RecordOnOnePage).List();

            return results;
        }


        public IEnumerable<Song> GetSongsByUsername(int userId)
        {
            //return db.Songs.Where(x => x.User.Username == username);

            //int userId = int.Parse(username);
            return FindAll(x => x.User.Id == userId).ToList();
        }

        public void EditSong(Song songObject)
        {
            //var obj = db.Songs.Where(x => x.SongId == songObject.SongId).FirstOrDefault();
            //if (obj != null)
            //{
            //    obj.SongName = songObject.SongName;
            //    obj.SongURL = songObject.SongURL;
            //    obj.Images = songObject.Images;
            //    obj.IsEmbed = songObject.IsEmbed;
            //    obj.Grammar = songObject.Grammar;
            //    obj.Singer = songObject.Singer;
            //    obj.Composer = songObject.Composer;
            //    db.SaveChanges();
            //}
            //else
            //{
            //    //throw new Exception(ConstantResource.NotExistedData);
            //}

            var obj = FindAll(x => x.Id == songObject.Id).FirstOrDefault();
            if (obj != null)
            {
                obj.SongName = songObject.SongName;
                obj.SongURL = songObject.SongURL;
                obj.Images = songObject.Images;
                obj.IsEmbed = songObject.IsEmbed;
                obj.Grammar = songObject.Grammar;
                obj.Singer = songObject.Singer;
                obj.Composer = songObject.Composer;
                SaveOrUpdate(obj);
            }
            else
            {
                //throw new Exception(ConstantResource.NotExistedData);
            }
        }


        public void EditGrammar(Song songObject)
        {
            //var obj = db.Songs.Where(x => x.SongId == songObject.SongId).FirstOrDefault();
            //obj.Grammar = songObject.Grammar;
            //db.SaveChanges();

            var obj = FindAll(x => x.Id == songObject.Id).FirstOrDefault();
            obj.Grammar = songObject.Grammar;
            SaveOrUpdate(obj);
        }

        public void EditSongFiles(Song songObject)
        {
            throw new NotImplementedException();
        }

        public void AddLyric(LyricDetail lyricObject)
        {
            //db.LyricDetails.Add(lyricObject);
            //db.SaveChanges();

            SaveOrUpdate(lyricObject);
        }

        public void EditLyric(IEnumerable<LyricDetail> lyricObjects)
        {
            //foreach (var item in lyricObjects)
            //{
            //    var lyric = db.LyricDetails.Where(x => x.SongId == item.SongId && x.LanguageId == item.LanguageId).FirstOrDefault();
            //    lyric.Language = item.Language;
            //    lyric.LyricContent = item.LyricContent;
            //}
            //db.SaveChanges();

            foreach (var item in lyricObjects)
            {
                //var lyric = Session.QueryOver<LyricDetail>().Where(x => x.SongId == item.SongId && x.LanguageId == item.LanguageId).List().FirstOrDefault();
                var lyric = Session.QueryOver<LyricDetail>().Where(x => x.Song.Id == item.Song.Id && x.Language.Id == item.Language.Id).List().FirstOrDefault();
                lyric.Language = item.Language;
                lyric.LyricContent = item.LyricContent;
                SaveOrUpdate(lyric);
            }
        }


        public IEnumerable<LyricDetail> GetLyricBySongId(int songId)
        {
            //return db.LyricDetails.Where(x => x.SongId == songId).ToList();
            return Session.QueryOver<LyricDetail>().Where(x => x.Song.Id == songId).List();
        }


        public void UpdateScore(int userId, int score)
        {
            //var obj = db.Users.Where(x => x.Username == username).FirstOrDefault();
            //obj.Score += score;
            //db.SaveChanges();

            //var obj = Session.QueryOver<User>().Where(x => x.Username == username).List().FirstOrDefault();
            var obj = Session.QueryOver<User>().Where(x => x.Id == userId).List().FirstOrDefault();
            obj.Point += score;
            SaveOrUpdate(obj);
        }


        public void CommunityUpdateLyric(LyricDetail lyricDetail, int userId)
        {
            //var obj = db.LyricDetails
            //    .Where(x => x.SongId == lyricDetail.SongId && x.LanguageId == lyricDetail.LanguageId)
            //    .FirstOrDefault();
            //if (obj != null)
            //{
            //    obj.LyricContent = lyricDetail.LyricContent;
            //    obj.UpdateUser = db.Users.Where(x => x.Username == username).FirstOrDefault().UserId;
            //    obj.LastUpdate = DateTime.Now;
            //    db.SaveChanges();
            //}
            //else
            //{
            //    //throw new Exception(ConstantResource.UpdateFail);
            //}

            var obj = Session.QueryOver<LyricDetail>()
                //.Where(x => x.SongId == lyricDetail.SongId && x.LanguageId == lyricDetail.LanguageId).List().FirstOrDefault();
                .Where(x => x.Song.Id == lyricDetail.Song.Id && x.Language.Id == lyricDetail.Language.Id).List().FirstOrDefault();
            if (obj != null)
            {
                obj.LyricContent = lyricDetail.LyricContent;
                //obj.User = Session.QueryOver<User>().Where(x => x.Username == username).List().FirstOrDefault();
                obj.User = Session.QueryOver<User>().Where(x => x.Id == userId).List().FirstOrDefault();
                obj.LastUpdate = DateTime.Now;
                SaveOrUpdate(obj);
            }
            else
            {
                //throw new Exception(ConstantResource.UpdateFail);
            }
        }

        public void CommunityUpdateEmbedLink(Song songObject, int userId)
        {
            //var obj = db.Songs
            //   .Where(x => x.SongId == songObject.SongId)
            //   .FirstOrDefault();
            //if (obj != null && string.IsNullOrEmpty(obj.SongURL))
            //{
            //    obj.SongURL = songObject.SongURL;
            //    obj.IsEmbed = true;
            //    db.SaveChanges();
            //}
            //else
            //{
            //    //throw new Exception(ConstantResource.UpdateFail);
            //}

            var obj = Session.QueryOver<Song>()
               .Where(x => x.Id == songObject.Id).List().FirstOrDefault();
            if (obj != null && string.IsNullOrEmpty(obj.SongURL))
            {
                obj.SongURL = songObject.SongURL;
                obj.IsEmbed = true;
                SaveOrUpdate(obj);
            }
            else
            {
                //throw new Exception(ConstantResource.UpdateFail);
            }
        }

        public IEnumerable<Language> GetLanguage(bool isSelectAll, int songId = 0)
        {
            //if (isSelectAll)
            //{
            //    return db.Languages;
            //}
            //var songObj = db.Songs.Where(x => x.SongId == songId).FirstOrDefault();
            //if (songObj != null)
            //{
            //    var languageList = new List<Language>(db.Languages);
            //    songObj.LyricDetails.ToList().ForEach((item) =>
            //    {
            //        var removedItem = languageList.Where(x => x.LanguageId == item.LanguageId).FirstOrDefault();
            //        languageList.Remove(removedItem);
            //    });
            //    return languageList.ToList();
            //}
            //else
            //{
            //    return db.Languages.ToList();
            //}

            if (isSelectAll)
            {
                return Session.QueryOver<Language>().List();
            }
            var songObj = Session.QueryOver<Song>().Where(x => x.Id == songId).List().FirstOrDefault();
            if (songObj != null)
            {
                var languageList = Session.QueryOver<Language>().List();
                songObj.LyricDetails.ToList().ForEach((item) =>
                {
                    var removedItem = languageList.Where(x => x.Id == item.Language.Id).FirstOrDefault();
                    languageList.Remove(removedItem);
                });
                return languageList.ToList();
            }
            else
            {
                return Session.QueryOver<Language>().List();
            }
        }


        public void CommunityAddMoreLyric(LyricDetail lyric)
        {
            //var checkObj = db.LyricDetails.Where(x => x.LanguageId == lyric.LanguageId && x.SongId == lyric.SongId).FirstOrDefault();
            //if (checkObj == null)
            //{
            //    db.LyricDetails.Add(lyric);
            //    db.SaveChanges();
            //}
            //else
            //{
            //    //throw new Exception(ConstantResource.ExistedData);
            //}

            //var checkObj = Session.QueryOver<LyricDetail>().Where(x => x.LanguageId == lyric.LanguageId && x.SongId == lyric.SongId).List().FirstOrDefault();
            var checkObj = Session.QueryOver<LyricDetail>().Where(x => x.Language.Id == lyric.Language.Id && x.Song.Id == lyric.Song.Id).List().FirstOrDefault();
            if (checkObj == null)
            {
                SaveOrUpdate(lyric);
            }
            else
            {
                //throw new Exception(ConstantResource.ExistedData);
            }
        }


        public void AddTestQuiz(QuestionQuiz model)
        {
            //db.QuestionQuizs.Add(model);
            //db.SaveChanges();
            SaveOrUpdate(model);
        }


        public void CommunityGrammar(Song song)
        {
            //var checkObj = db.Songs.Where(x => x.SongId == song.SongId && x.CanUpdateGrammar && x.CanUpdateGrammar).FirstOrDefault();
            //if (checkObj != null)
            //{
            //    checkObj.Grammar = song.Grammar;
            //    db.SaveChanges();
            //}
            //else
            //{
            //    //throw new Exception(ConstantResource.NotExistedData);
            //}

            var checkObj = Session.QueryOver<Song>().Where(x => x.Id == song.Id && x.CanUpdateGrammar && x.CanUpdateGrammar).List().FirstOrDefault();
            if (checkObj != null)
            {
                checkObj.Grammar = song.Grammar;
                SaveOrUpdate(checkObj);
            }
            else
            {
                //throw new Exception(ConstantResource.NotExistedData);
            }
        }


        public void AddTestBlank(QuestionBlank model)
        {
            //db.QuestionBlanks.Add(model);
            //db.SaveChanges();

            SaveOrUpdate(model);
        }


        public void LikeSong(int userId, int songId)
        {
            //var song = db.Songs.Where(x => x.SongId == songId).FirstOrDefault();

            //if (song != null)
            //{
            //    string[] listLiker = song.Liker.Split(',');
            //    if (!listLiker.Contains(username))
            //    {
            //        song.LikeTime += 1;
            //        song.Liker += "," + username;
            //        db.SaveChanges();
            //    }
            //    else
            //    {
            //        throw new Exception(ConstantResource.ExistedData);
            //    }
            //}
            //else
            //    throw new Exception(ConstantResource.NotExistedData);

            var song = Session.QueryOver<Song>().Where(x => x.Id == songId).List().FirstOrDefault();

            if (song != null)
            {
                string[] listLiker = song.Liker.Split(',');
                if (!listLiker.Contains(userId.ToString()))
                {
                    song.LikeTime += 1;
                    song.Liker += "," + userId.ToString();
                    SaveOrUpdate(song);
                }
                else
                {
                    throw new Exception("ConstantResource.ExistedData");
                }
            }
            else
                throw new Exception("ConstantResource.NotExistedData");
        }


        public IEnumerable<Song> SearchSong(string keyword, int pageNumber, bool isOnlyUnapprove, int userId = 0)
        {
            //var list = db.Songs
            //    .Where(x => x.SongName.Contains(keyword) && x.User.Username.Contains(username))
            //    .OrderByDescending(x => x.SongName)
            //    .Skip((pageNumber - 1) * 15)
            //    .Take(15);
            //if (isOnlyUnapprove)
            //    return list.Where(x => x.SongStatus == false).ToList();
            //else
            //    return list.ToList();

            var list = Session.QueryOver<Song>()
                //.Where(x => x.SongName.Contains(keyword) && x.User.Username.Contains(username))
                .OrderBy(x => x.Id).Desc
                .Skip((pageNumber - 1) * 15)
                .Take(15)
                .List();

            if (isOnlyUnapprove)
                return list.Where(x => x.SongStatus == false).ToList();
            else
                return list.ToList();
        }


        public int SearchSongCount(string keyword, int pageNumber, bool isOnlyUnapprove, int userId = 0)
        {
            //var list = db.Songs
            //    .Where(x => x.SongName.Contains(keyword) && x.User.Username.Contains(username));
            //if (isOnlyUnapprove)
            //    return list.Where(x => x.SongStatus == false).Count();
            //else
            //    return list.Count();

            var list = Session.QueryOver<Song>()
                //.Where(x => x.SongName.Contains(keyword) && x.User.Username.Contains(username))
                .List();

            if (isOnlyUnapprove)
                return list.Where(x => x.SongStatus == false).Count();
            else
                return list.Count();
        }


        public void UpdateTestBlank(QuestionBlank model)
        {
            //var obj = db.QuestionBlanks.Where(x => x.BlankId == model.BlankId).FirstOrDefault();
            //obj.BlankContent = model.BlankContent;
            //obj.PostedDate = model.PostedDate;
            //db.SaveChanges();

            var obj = Session.QueryOver<QuestionBlank>().Where(x => x.Id == model.Id).List().FirstOrDefault();
            obj.BlankContent = model.BlankContent;
            obj.PostedDate = model.PostedDate;
            SaveOrUpdate(obj);
        }


        public void UpdateTestQuiz(QuestionQuiz model)
        {
            //var obj = db.QuestionQuizs.Where(x => x.QuizId == model.QuizId).FirstOrDefault();
            //obj.QuizContent = model.QuizContent;
            //obj.PostedDate = model.PostedDate;
            //db.SaveChanges();

            var obj = Session.QueryOver<QuestionQuiz>().Where(x => x.Id == model.Id).List().FirstOrDefault();
            obj.QuizContent = model.QuizContent;
            obj.PostedDate = model.PostedDate;
            SaveOrUpdate(obj);
        }


        public void DeleteTest(int testId, bool type)
        {
            //if (type)
            //{
            //    db.QuestionBlanks.Remove(db.QuestionBlanks.Where(x => x.BlankId == testId).FirstOrDefault());
            //}
            //else
            //{
            //    db.QuestionQuizs.Remove(db.QuestionQuizs.Where(x => x.QuizId == testId).FirstOrDefault());
            //}
            //db.SaveChanges();

            if (type)
            {
                Delete(Session.QueryOver<QuestionBlank>().Where(x => x.Id == testId).List().FirstOrDefault());
            }
            else
            {
                Delete(Session.QueryOver<QuestionQuiz>().Where(x => x.Id == testId).List().FirstOrDefault());
            }
        }


        public void ApproveLyric(int lyricId, bool typeAction)
        {
            //var obj = db.LyricDetails.Where(x => x.ID == lyricId).FirstOrDefault();
            //obj.LyricStatus = typeAction;
            //db.SaveChanges();

            var obj = Session.QueryOver<LyricDetail>().Where(x => x.Id == lyricId).List().FirstOrDefault();
            obj.LyricStatus = typeAction;
            SaveOrUpdate(obj);
        }

        //Home repository moved
        public IEnumerable<Song> GetTopHighestSongs()
        {
            //return db.Songs
            //    .OrderByDescending(x => x.LikeTime)
            //    .Take(ConstantData.RecordOnOnePage).ToList();

            return Session.QueryOver<Song>()
                .OrderBy(x => x.Id).Desc               
                .Take(ConstantData.RecordOnOnePage).List();
        }

        public IEnumerable<QA> GetTopNewestQAs()
        {
            //return db.QAs.OrderByDescending(x => x.PostedDate).Take(ConstantData.RecordOnOnePage * 2).ToList();
            return Session.QueryOver<QA>().OrderBy(x => x.PostedDate).Desc.Take(ConstantData.RecordOnOnePage * 2).List();
        }

        public IEnumerable<User> GetTopHighestUsers()
        {
            //return db.Users
            //    .OrderByDescending(x => x.Score)
            //    .Take(ConstantData.RecordOnOnePage).ToList();

            return Session.QueryOver<User>()
                .OrderBy(x => x.Point).Desc
                .Take(ConstantData.RecordOnOnePage).List();
        }

        public int TotalSongCount()
        {
            //return db.Songs.Count();
            return Session.QueryOver<Song>().List().Count();
        }

        public int TotalUserCount()
        {
            //return db.Users.Count();
            return Session.QueryOver<User>().List().Count();
        }

        public int TotalThreadCount()
        {
            //return db.QAs.Count();
            return Session.QueryOver<QA>().List().Count();
        }

        public IEnumerable<Song> GetSearchSongs(string keyword)
        {
            //return db.Songs.Where(x => x.SongName.Contains(keyword)).ToList();
            return Session.QueryOver<Song>().Where(x => x.SongName.Contains(keyword)).List();
        }

        //favorated song
        public void AddFavouriteSong(int songId, int userId)
        {
            //var obj = db.FavouriteSongs
            //    .Where(x => x.SongId == songId && x.Users == db.Users.Where(u => u.Username == username).FirstOrDefault().UserId)
            //    .FirstOrDefault();
            //if (obj == null)
            //{
            //    try
            //    {
            //        db.FavouriteSongs.Add(new FavouriteSong { SongId = songId, Users = db.Users.Where(u => u.Username == username).FirstOrDefault().UserId });
            //        db.SaveChanges();
            //    }
            //    catch
            //    {
            //        //TO DO
            //        throw new Exception(ConstantResource.GeneralError);
            //    }
            //}
            //else
            //{
            //    throw new Exception(ConstantResource.ExistedData);
            //}

            var obj = Session.QueryOver<FavouriteSong>()
                .Where(x => x.Song.Id == songId && x.User.Id == Session.QueryOver<User>().Where(u => u.Id == userId).List().FirstOrDefault().Id)
                .List().FirstOrDefault();
            if (obj == null)
            {
                try
                {
                    var favouriteSong = new FavouriteSong { Song = Session.QueryOver<Song>().Where(u => u.Id == songId).List().FirstOrDefault()
                        , User = Session.QueryOver<User>().Where(u => u.Id == userId).List().FirstOrDefault() };
                    SaveOrUpdate(favouriteSong);
                }
                catch
                {
                    //TO DO
                    throw new Exception("ConstantResource.GeneralError");
                }
            }
            else
            {
                throw new Exception("ConstantResource.ExistedData");
            }
        }

        public void DeleteFavouriteSong(int songId, int userId)
        {
            //var obj = db.FavouriteSongs
            //    .Where(x => x.SongId == songId && x.Users == db.Users.Where(u => u.Username == username).FirstOrDefault().UserId)
            //    .FirstOrDefault();
            //if (obj != null)
            //{
            //    try
            //    {
            //        db.FavouriteSongs.Remove(obj);
            //        db.SaveChanges();
            //    }
            //    catch
            //    {
            //        //TO DO
            //        throw new Exception(ConstantResource.GeneralError);
            //    }
            //}
            //else
            //{
            //    throw new Exception(
            //        ConstantResource.NotExistedData +
            //        Environment.NewLine +
            //        ConstantResource.NotOwner);
            //}

            var obj = Session.QueryOver<FavouriteSong>()
                .Where(x => x.Song.Id == songId && x.User.Id == Session.QueryOver<User>().Where(u => u.Id == userId).List().FirstOrDefault().Id)
                .List().FirstOrDefault();
            if (obj != null)
            {
                try
                {
                    Delete(obj);
                }
                catch
                {
                    //TO DO
                    throw new Exception("ConstantResource.GeneralError");
                }
            }
            else
            {
                throw new Exception(
                    "ConstantResource.NotExistedData" +
                    "Environment.NewLine" +
                    "ConstantResource.NotOwner");
            }
        }

        public IEnumerable<FavouriteSong> GetMyFavouriteSongs(int userId, string keyword, out int totalItem, int page = 1)
        {
            //var list = db.FavouriteSongs.Where(x => x.User.Username == username && x.Song.SongName.Contains(keyword));
            //totalItem = list.Count() / ConstantData.RecordOnOnePageListItem;
            //return list
            //    .OrderByDescending(x => x.SongId)
            //    .Skip((page - 1) * ConstantData.RecordOnOnePageListItem)
            //    .Take(ConstantData.RecordOnOnePageListItem).ToList();

            var list = Session.QueryOver<FavouriteSong>().Where(x => x.User.Id == userId
                    //&& x.Song.SongName.Contains(keyword) == true //TODO: to be implemented for this condition
                    ).List();
            totalItem = list.Count() / ConstantData.RecordOnOnePageListItem;
            return list
                .OrderByDescending(x => x.Song.Id)
                .Skip((page - 1) * ConstantData.RecordOnOnePageListItem)
                .Take(ConstantData.RecordOnOnePageListItem).ToList();
        }

        //Friend
        public IEnumerable<Relationship> GetFriendsByUsername(int userId, int page = 1)
        {
            //return db.Relationships.Where(x => x.User1 == db.Users.Where(u => u.Username == username).FirstOrDefault().UserId)
            //    .OrderByDescending(x => x.User2)
            //    .Skip((page - 1) * ConstantData.RecordOnOnePage)
            //    .Take(ConstantData.RecordOnOnePage).ToList();

            return Session.QueryOver<Relationship>().Where(x => x.User1.Id == Session.QueryOver<User>().Where(u => u.Id == userId).List().FirstOrDefault().Id)
                .OrderBy(x => x.User2).Desc
                .Skip((page - 1) * ConstantData.RecordOnOnePage)
                .Take(ConstantData.RecordOnOnePage).List();
        }

        public void AddFriend(int userId1, int userId2)
        {
            //var user1 = db.Users.Where(x => x.Username == username1).FirstOrDefault();
            //var user2 = db.Users.Where(x => x.Username == username2).FirstOrDefault();
            //if (user1 != null && user2 != null)
            //{
            //    var obj = db.Relationships.Where(x => x.User1 == user1.UserId && x.User2 == user2.UserId).FirstOrDefault();
            //    if (obj == null)
            //    {
            //        db.Relationships.Add(new Relationship()
            //        {
            //            User1 = user1.UserId,
            //            User2 = user2.UserId
            //        });
            //        db.Relationships.Add(new Relationship()
            //        {
            //            User1 = user2.UserId,
            //            User2 = user1.UserId
            //        });
            //        db.SaveChanges();
            //        return;
            //    }
            //}
            //throw new Exception(ConstantResource.ExistedData);

            var user1 = Session.QueryOver<User>().Where(x => x.Id == userId1).List().FirstOrDefault();
            var user2 = Session.QueryOver<User>().Where(x => x.Id == userId2).List().FirstOrDefault();
            if (user1 != null && user2 != null)
            {
                var obj = Session.QueryOver<Relationship>().Where(x => x.User1.Id == user1.Id && x.User2.Id == user2.Id).List().FirstOrDefault();
                if (obj == null)
                {
                    Relationship Relationship1 = new Relationship()
                    {
                        User1 = user1,
                        User2 = user2
                    };

                    Relationship Relationship2 = new Relationship()
                    {
                        User1 = user2,
                        User2 = user1
                    };

                    SaveOrUpdate(Relationship1);
                    SaveOrUpdate(Relationship2);

                    return;
                }
            }
            throw new Exception("ConstantResource.ExistedData");
        }


        public void DeleteFriends(int userId1, int userId2)
        {
            throw new NotImplementedException();
        }

        //relationshipt
        public IEnumerable<Relationship> GetFriends(int userId, out int totalItems, string keyword, int pageNumber = 1)
        {
            //var list = db.Relationships.Where(x => x.User1 == userId && (x.User3.Username.Contains(keyword) || x.User3.Fullname.Contains(keyword)));
            //totalItems = list.Count();
            //return list
            //    .OrderByDescending(x => x.User3.Username)
            //    .Skip((pageNumber - 1) * ConstantData.RecordOnOnePageListItem)
            //    .Take(ConstantData.RecordOnOnePageListItem)
            //    .ToList();

            var list = Session.QueryOver<Relationship>().Where(x => x.User1.Id == userId
                // && (x.User3.DisplayName.Contains(keyword)  || x.User3.DisplayName.Contains(keyword))//TODO: to be implemented for this condition
                 )
                 //.JoinQueryOver(u => u.User3).Where(Restrictions.On<User>(u => u.DisplayName).IsLike("%" +  keyword + "%"))
                .List();
            totalItems = list.Count();
            return list
                .OrderByDescending(x => x.User2.Id)
                .Skip((pageNumber - 1) * ConstantData.RecordOnOnePageListItem)
                .Take(ConstantData.RecordOnOnePageListItem)
                .ToList();
        }

        public void DeleteFriend(int userId1, int userId2)
        {
            //var user1 = db.Users.Where(x => x.Username == username1).FirstOrDefault();
            //var user2 = db.Users.Where(x => x.Username == username2).FirstOrDefault();
            //if (user1 != null && user2 != null)
            //{
            //    var obj = db.Relationships.Where(x => x.User1 == user1.UserId && x.User2 == user2.UserId).FirstOrDefault();
            //    if (obj != null)
            //    {
            //        db.Relationships.Remove(obj);
            //        db.SaveChanges();
            //        return;
            //    }
            //}
            //throw new Exception(ConstantResource.GeneralError);

            var user1 = Session.QueryOver<User>().Where(x => x.Id == userId1).List().FirstOrDefault();
            var user2 = Session.QueryOver<User>().Where(x => x.Id == userId2).List().FirstOrDefault();
            if (user1 != null && user2 != null)
            {
                var obj = Session.QueryOver<Relationship>().Where(x => x.User1.Id == user1.Id && x.User2.Id == user2.Id).List().FirstOrDefault();
                if (obj != null)
                {
                    Delete(obj);
                    return;
                }
            }
            throw new Exception("ConstantResource.GeneralError");
        }

        //SongBankTestRepository
        public LyricDetail Get_SongLyric(int SongID)
        {
            ////cài này dùng để lấy nội dung câu hỏi
            //LyricDetail lyric;
            //lyric = (from s in db.LyricDetails where s.SongId == SongID select s).First();
            //return lyric;

            //cài này dùng để lấy nội dung câu hỏi
            LyricDetail lyric;
            lyric = Session.QueryOver<LyricDetail>().Where(x => x.Song.Id == SongID).List().FirstOrDefault();
            return lyric;
        }

        public void Save_SongLyric(QuestionBlank question)
        {
            //db.QuestionBlanks.Add(question);
            //db.SaveChanges();

            SaveOrUpdate(question);
        }

        public Song Get_SongSong(int songid)
        {
            ////lên tạp thời dùng cái này
            //Song song;
            //song = (from s in db.Songs where s.SongId == songid select s).FirstOrDefault();
            //return song;

            //lên tạp thời dùng cái này
            Song song;
            song = Session.QueryOver<Song>().Where(x => x.Id == songid).List().FirstOrDefault();
            return song;
        }

        public QuestionBlank Get_QuestionBank(int songid)
        {
            //QuestionBlank question;
            //question = (from q in db.QuestionBlanks where q.SongId == songid select q).FirstOrDefault();
            //return question;

            QuestionBlank question;
            question = Session.QueryOver<QuestionBlank>().Where(x => x.Song.Id == songid).List().FirstOrDefault();
            return question;
        }

        //Song comment
        public IEnumerable<SongComment> GetSongSommentsBySongId(int songId, out int totalPageCount, int page = 1)
        {
            //var list = db.SongComments
            //    .Where(x => x.SongId == songId)
            //    .OrderByDescending(x => x.PostedDate);
            //int totalResult = list.Count();
            //totalPageCount = totalResult / ConstantData.RecordOnOnePage;
            //if (totalPageCount * ConstantData.RecordOnOnePage < totalResult)
            //{
            //    totalPageCount++;
            //}

            //var pagedList = list.Skip((page - 1) * ConstantData.RecordOnOnePage).Take(ConstantData.RecordOnOnePage);
            ////foreach (var item in list)
            ////{
            ////    item.User = db.Users.Where(x=>x.Username == item.User.Username).FirstOrDefault();
            ////}
            //Task.WaitAll();
            //return pagedList.ToList();

            var list = Session.QueryOver<SongComment>()
                .Where(x => x.SongId == songId)
                .OrderBy(x => x.PostedDate).Desc.List();
            int totalResult = list.Count();
            totalPageCount = totalResult / ConstantData.RecordOnOnePage;
            if (totalPageCount * ConstantData.RecordOnOnePage < totalResult)
            {
                totalPageCount++;
            }

            var pagedList = list.Skip((page - 1) * ConstantData.RecordOnOnePage).Take(ConstantData.RecordOnOnePage);
            //foreach (var item in list)
            //{
            //    item.User = db.Users.Where(x=>x.Username == item.User.Username).FirstOrDefault();
            //}
            //Task.WaitAll();
            return pagedList.ToList();
        }

        public IEnumerable<SongComment> GetAllSongComments(int page = 1)
        {
            return new List<SongComment>();
        }

        public SongComment GetCommentContent(int commentId)
        {
            //return db.SongComments.Where(x => x.CommentId == commentId).FirstOrDefault();
            return Session.QueryOver<SongComment>().Where(x => x.Id == commentId).List().FirstOrDefault();
        }

        public int AddComment(SongComment songObject)
        {
            //db.SongComments.Add(songObject);
            //db.SaveChanges();
            //return songObject.CommentId;

            SaveOrUpdate(songObject);
            return songObject.Id;
        }

        public void DeleteComment(int commentId)
        {
            throw new NotImplementedException();
        }

        public void UpdateComment(int commentId, string commentContent)
        {
            //var obj = db.SongComments.Where(x => x.CommentId == commentId).FirstOrDefault();
            //if (obj != null)
            //{
            //    obj.CommentContent = commentContent;
            //    db.SaveChanges();
            //}
            //else
            //{
            //    throw new Exception(ConstantResource.NotExistedData);
            //}

            var obj = Session.QueryOver<SongComment>().Where(x => x.Id == commentId).List().FirstOrDefault();
            if (obj != null)
            {
                obj.CommentContent = commentContent;
                SaveOrUpdate(obj);
            }
            else
            {
                throw new Exception("ConstantResource.NotExistedData");
            }
        }

        //song report
        public void AddReport(SongReport report)
        {
            //try
            //{
            //    db.SongReports.Add(report);
            //    db.SaveChanges();
            //}
            //catch
            //{

            //}

            try
            {
                SaveOrUpdate(report);
            }
            catch
            {

            }
        }

        public IEnumerable<SongReport> GetAllReport(int page = 1, int number = 10, string ReportType = "1")
        {
            //var model = db.SongReports
            //    .Where(x => x.ReportType == ReportType)
            //    .OrderBy(x => x.ReportDate)
            //    .Skip((page - 1) * number)
            //    .Take(number)
            //    .ToList();
            //return model;

            var model = Session.QueryOver<SongReport>()
                .Where(x => x.ReportType == ReportType)
                .OrderBy(x => x.ReportDate).Asc
                .Skip((page - 1) * number)
                .Take(number)
                .List();
            return model;
        }

        public SongReport GetReport(int reportId)
        {
            throw new NotImplementedException();
        }

        public void DeleteReport(int reportId)
        {
            //SongReport song = db.SongReports.Where(x => x.ID == reportId).FirstOrDefault();
            //db.SongReports.Remove(song);
            //db.SaveChanges();

            SongReport songReport = Session.QueryOver<SongReport>().Where(x => x.Id == reportId).List().FirstOrDefault();
            Delete(songReport);
        }

        public IEnumerable<SongReport> GetSongReport(int songid, int page = 1, int number = 10)
        {
            //var model = db.SongReports
            //    .Where(x => x.SongID == songid & x.ReportType == "1")
            //    .OrderBy(x => x.ReportDate)
            //    .Skip((page - 1) * number)
            //    .Take(number)
            //    .ToList();
            //return model;

            var model = Session.QueryOver<SongReport>()
                .Where(x => x.SongID == songid & x.ReportType == "1")
                .OrderBy(x => x.ReportDate).Asc
                .Skip((page - 1) * number)
                .Take(number)
                .List();
            return model;
        }

        public IEnumerable<SongReport> GetLyricReport(int songid, int Lyric, int page = 1, int number = 10)
        {
            //var model = db.SongReports
            //    .Where(x => x.SongID == songid & x.LyricID == Lyric & x.ReportType == "2")
            //    .OrderBy(x => x.ReportDate)
            //    .Skip((page - 1) * number)
            //    .Take(number)
            //    .ToList();
            //return model;

            var model = Session.QueryOver<SongReport>()
                .Where(x => x.SongID == songid & x.LyricID == Lyric & x.ReportType == "2")
                .OrderBy(x => x.ReportDate).Asc
                .Skip((page - 1) * number)
                .Take(number)
                .List();
            return model;
        }

        public IEnumerable<SongReport> GetCommentReport(int songid, int commentid, int page = 1, int number = 10)
        {
            //var model = db.SongReports
            //    .Where(x => x.SongID == songid & x.CommentID == commentid & x.ReportType == "3")
            //    .OrderBy(x => x.ReportDate)
            //    .Skip((page - 1) * number)
            //    .Take(number)
            //    .ToList();
            //return model;

            var model = Session.QueryOver<SongReport>()
                .Where(x => x.SongID == songid & x.CommentID == commentid & x.ReportType == "3")
                .OrderBy(x => x.ReportDate).Asc
                .Skip((page - 1) * number)
                .Take(number)
                .List();
            return model;
        }

        public void UpdateStatus(SongReport songreport)
        {
            //db.SongReports.Add(songreport);
            //db.SaveChanges();

            SaveOrUpdate(songreport);
        }

        public IEnumerable<BadWordsFilter> GetBadWord()
        {
            var model = Session.QueryOver<BadWordsFilter>()
                //.Where(x => x.Language == langugeId)
                .List();
            return model;
        }

        public void AddBadWork(BadWordsFilter BadWords)
        {

            //db.BadWordsFilters.Add(BadWords);
            //db.SaveChanges();

            SaveOrUpdate(BadWords);

        }

        public bool CheckExistBadWord(string BadWord, int lang)
        {
            //try
            //{
            //    var model = db.BadWordsFilters.Where(x => x.Language == lang & x.Words == BadWord).ToList();
            //    if (model.Count() > 0)
            //        return true;
            //    else
            //        return false;
            //}
            //catch
            //{
            //    return false;
            //}

            try
            {
                var model = Session.QueryOver<BadWordsFilter>().Where(x => x.Language == lang & x.Words == BadWord).List();
                if (model.Count() > 0)
                    return true;
                else
                    return false;
            }
            catch
            {
                return false;
            }
        }

        public int SumReport(string type, int id)
        {
            //var model = db.SongReports.Where(x => x.SongID == id & x.ReportType == type).ToList();
            //return model.Count();

            var model = Session.QueryOver<SongReport>().Where(x => x.SongID == id & x.ReportType == type).List();
            return model.Count();
        }

        public int SumReportType(string type)
        {
            //var model = db.SongReports.Where(x => x.ReportType == type).ToList();
            //return model.Count();

            var model = Session.QueryOver<SongReport>().Where(x => x.ReportType == type).List();
            return model.Count();
        }

        public IEnumerable<UserNote> GetNotes(int userId, out int total, int currentPage)
        {
            //var user = FindUserById(username);
            //var list = user.UserNotes
            //    .OrderByDescending(x => x.CreatedDate);
            //int totalResult = list.Count();
            //total = totalResult / ConstantData.RecordOnOnePage;
            //if (total * ConstantData.RecordOnOnePage < totalResult)
            //{
            //    total++;
            //}
            //var pagedList = list.Skip((currentPage - 1) * ConstantData.RecordOnOnePage).Take(ConstantData.RecordOnOnePage);
            //return pagedList;

            var user = Session.QueryOver<User>().Where(x => x.Id == userId).List().FirstOrDefault();
            var list = Session.QueryOver<UserNote>()
                .Where(x => x.UserId == user.Id)
                .OrderBy(x => x.CreatedDate).Desc.List();

            int totalResult = list.Count();
            total = totalResult / ConstantData.RecordOnOnePage;
            if (total * ConstantData.RecordOnOnePage < totalResult)
            {
                total++;
            }
            var pagedList = list.Skip((currentPage - 1) * ConstantData.RecordOnOnePage).Take(ConstantData.RecordOnOnePage);
            return pagedList;
        }

        //QA
        //lấy danh sách QA xem nhiều nhất
        public IList<QA> QA_TopView()
        {
            //IList<QA> qa;
            //qa = (from b in db.QAs orderby b.SumView descending select b).Take(10).ToList();
            //return qa;

            IList<QA> qa;
            qa = Session.QueryOver<QA>().OrderBy(x => x.SumView).Desc.Take(10).List();
            return qa;
        }
        //lấy danh sách QA theo loại
        public IList<QA> QA_Catagory(string para)
        {
            IList<QA> qa;
            //qa = db.QAs.Where(q => q.QuestionCatagory == para).Take(10).ToList();
            qa = Session.QueryOver<QA>().Where(q => q.QuestionCatagory == para).Take(10).List();
            return qa;
        }
        //Lấy danh sách QA mới nhất 10 dòng
        public IList<QA> QA_TopNew()
        {
            IList<QA> qa;
            //qa = (from b in db.QAs orderby b.PostedDate descending select b).Take(10).ToList();
            qa = Session.QueryOver<QA>().OrderBy(x => x.PostedDate).Desc.Take(10).List();
            return qa;
        }
        //Lấy danh sách QA được comment nhiều nhất(trả lời) 10 dòng
        public IList<QA> QA_TopAnsert()
        {
            IList<QA> qa;
            //qa = (from b in db.QAs orderby b.SumAnsert descending select b).Take(10).ToList();
            qa = Session.QueryOver<QA>().OrderBy(x => x.SumAnsert).Desc.Take(10).List();
            return qa;
        }
        //lấy danh sách QA xem nhiều nhất chỉ lấy 5 dòng
        public IList<QA> QA_TopNew5()
        {
            IList<QA> qa;
            //qa = (from b in db.QAs orderby b.PostedDate descending select b).Take(5).ToList();
            qa = Session.QueryOver<QA>().OrderBy(x => x.PostedDate).Desc.Take(5).List();
            return qa;
        }
        //tìm QA với mã truyền vào
        public QA FindQaByID(int QaId)
        {
            QA qa;// = db.QAs.Where(q => q.QuestionId == QaId).First();
            qa = Session.QueryOver<QA>().Where(q => q.Id == QaId).List().FirstOrDefault();
            return qa;
        }
        //tạo mới 1 QA
        public void CreateQA(QA Qa)
        {
            //db.QAs.Add(Qa);
            //db.SaveChanges();
            SaveOrUpdate(Qa);
        }
        //
        public void UpdateView(QA Qa)
        {
            //var QA = db.QAs.Where(q => q.QuestionId == Qa.QuestionId).FirstOrDefault();
            var QA = Session.QueryOver<QA>().Where(q => q.Id == Qa.Id).List().FirstOrDefault();
            QA.SumView = Qa.SumView;
            //db.SaveChanges();
            SaveOrUpdate(QA);
        }
        //tạo mới 1 QA comment
        public void CreateComany(QAComment Qacom)
        {
            //db.QAComments.Add(Qacom);
            //db.SaveChanges();
            SaveOrUpdate(Qacom);
        }
        //thanks
        public void UpdateThanks(QA Qa)
        {
            //var QA = db.QAs.Where(q => q.QuestionId == Qa.QuestionId).FirstOrDefault();
            var QA = Session.QueryOver<QA>().Where(q => q.Id == Qa.Id).List().FirstOrDefault();
            QA.Thanks = Qa.Thanks;
            //db.SaveChanges();
            SaveOrUpdate(QA);
        }
        //tim user name
        public string SreachUserName(int ID)
        {
            //var user = db.Users.Where(u => u.UserId == ID).FirstOrDefault();
            var user = Session.QueryOver<User>().Where(u => u.Id == ID).List().FirstOrDefault();
            if (user == null) return "";

            return StringHelper.ToString(user.Username);
        }
    }
}
